<script lang="ts" setup>
import { Cascader,  Form, Input, Switch, Select, InputNumber } from 'ant-design-vue'
import {
  type IBeforeCaseStep, 
  defaultWithIBeforeCaseStep, 
  defaultWithIBeforeConstantSelectOptions, 
  defaultWithIBeforeCase,
} from '../../../types/apis/before-case'

import BeforeCaseStep from '~/components/NewOrEdit/BeforeCaseStep.vue'
import BeforeDatabaseStep from '~/components/NewOrEdit/BeforeDatabaseStep.vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
import { useCustomFetch } from '../../../composables/custom-fetch'
import type { IBasic } from '../../../types/apis/basic'
import type { ColumnsType } from 'ant-design-vue/es/table'
import type { IOperation } from '../../../types/apis/ui'
import type { AfterFetchContext } from '@vueuse/core/index.cjs'
import { objectOmit } from '@vueuse/core'
import type {
  CascaderProps,
  ShowSearchType,
} from 'ant-design-vue/es/vc-cascader'
import { reactive, watch,ref } from 'vue'
import {useGlobalConfigStore} from '../../../stores/global-config.store'


const globalConfig = useGlobalConfigStore()

const columns: ColumnsType<any> = [
  {
    title: '序号',
    dataIndex: 'id',
    key: 'id',
    fixed: 'left',
    align: 'center',
  },
  { title: '排序', dataIndex: 'num', key: 'num', align: 'center' },
  { title: '名称', dataIndex: 'name', key: 'name', align: 'center' },
  {
    title: '描述',
    dataIndex: 'description',
    key: 'description',
    align: 'center',
  },
  { title: '路径', dataIndex: 'path', key: 'path', align: 'center' },
  { title: '等级', dataIndex: 'level', key: 'level', align: 'center' },
  {
    title: '环境 ID',
    dataIndex: 'environmentId',
    key: 'environmentId',
    align: 'center',
  },
  { title: '请求类型', dataIndex: 'method', key: 'method', align: 'center' },
  {
    title: '修改时间',
    dataIndex: 'gmtModified',
    key: 'gmtModified',
    width: 200,
    align: 'center',
  },
  {
    title: '操作',
    dataIndex: 'operation',
    key: 'operation',
    fixed: 'right',
    width: 170,
    align: 'center',
  },
]
type ResponseType = Record<
  | 'ui_location_type'
  | 'browser'
  | 'mouse'
  | 'keyboard'
  | 'wait'
  | 'assertion'
  | 'browser_type'
  | 'img',
  IOperation[]
>

const { data } = useCustomFetch<ResponseType>(
  '/engine-service/api/v1/dict/list?category=ui_location_type,browser,mouse,keyboard,wait,assertion,img,browser_type,combination, select, iframe',
  {
    initialData: {},
    afterFetch(ctx: AfterFetchContext<IBasic<ResponseType>>) {
      if (ctx.data && ctx.data.code === 0) {
        return {
          data: ctx.data.data,
          response: ctx.response,
        }
      }
      return {
        data: [],
        response: ctx.response,
      }
    },
  },
)

const currentSelectedOptions = ref<string[]>([])

const filter: ShowSearchType['filter'] = (inputValue, path) => {
  return path.some((option) =>
    option.label.toLowerCase().includes(inputValue.toLowerCase()),
  )
}
const cascaderOptions = computed(() => {
  if (!data.value) {
    return []
  }

  return Object.entries(
    objectOmit(data.value, ['ui_location_type', 'browser_type']),
  )
    .filter(([, value]) => value.length > 0)
    .map(([key, value]) => ({
      value: key,
      label: value?.[0]?.categoryName ?? '',
      children: value.map((item) => ({
        value: item.value,
        label: item.name,
      })),
    })) as CascaderProps['options']
})

const currentSelectedValue = computed(() => {
  const category =
    data.value?.[currentSelectedOptions.value?.[0] as keyof ResponseType]
  if (!category) {
    return []
  }
  const selected = category.find(
    (item) => item.value === currentSelectedOptions.value?.[1],
  )
  return selected
    ? objectDeserializer<{ name: string; field: string }>(selected.extend, true)
    : []
})

function initOperationType(type: string | undefined) {
  if (!type) return

  const found = cascaderOptions.value?.find(
    (item) => item.children?.find((child) => child.value === type) != null,
  )

  if (!found) return

  currentSelectedOptions.value = [
    found.value as string,
    found.children!.find((child) => child.value === type)!.value as string,
  ]
}


watch(() => globalConfig.selectedStep,
  (newValue) => {

    initOperationType(newValue.operationType)
  },
  { deep: true }
)

/**
 * 重试开关变动
 */
let isRetrySwitchType = ref(!globalConfig.selectedStep.isRetry);
watch(() => globalConfig.selectedStep.isRetry,
  (newValue) => {
    if(newValue){
      isRetrySwitchType.value = false
    }else{
      isRetrySwitchType.value = true
    }
  },
  { deep: true }
)
</script>

<template>
  <div >
    <!-- 下面的子<template>将ui和api的都放到一起了，然后defaultWithIBeforeCaseStep这些东西都有单独的一套Before的，解决问题： 切换ui和api类型时，第一次会刷新一下而不会弹出对应的【编辑/添加】的prop -->
    <NewOrEditSteps
      info="before"
      localized-name="前置用例"
      base-api-name="before_case"
      :columns="columns"
      :default-with-step-item="defaultWithIBeforeCaseStep"
      :default-with-step-instance="defaultWithIBeforeCase"
      :default-constant-select-options="defaultWithIBeforeConstantSelectOptions"
    >   
      <template #body-content="{ formModel }">
        <Form :modal="formModel" layout="horizontal" class="grid grid-cols-4 gap-4">
          <Form.Item label="用例名称">
            <Input v-model:value="formModel.name" placeholder="请输入用例名称" />
          </Form.Item>
          <Form.Item label="用例描述">
            <Input.TextArea
              v-model:value="formModel.description"
              placeholder="请输入用例描述"
            />
          </Form.Item>
        </Form>
      </template>

<!-- 添加API的弹窗 -->
      <template v-if="globalConfig.testType === 'API'" #model-content="{ selectedStep, setStepSlotRef, constantSelectOptions }">
        <BeforeCaseStep
          :ref="(el) => setStepSlotRef(el as ComponentExposed<typeof BeforeCaseStep>)"
          :before-constant-select-options="constantSelectOptions"
          :selected-step="selectedStep as IBeforeCaseStep"
        />
      </template>

      <!-- 添加DATABASE的弹窗 -->
      <template v-if="globalConfig.testType === 'DATABASE'" #model-content="{ selectedStep, setStepSlotRef, constantSelectOptions }">
        <BeforeDatabaseStep
          :ref="(el) => setStepSlotRef(el as ComponentExposed<typeof BeforeDatabaseStep>)"
          :before-constant-select-options="constantSelectOptions"
          :database-constant-select-options = "constantSelectOptions"
          :selected-step="selectedStep as IBeforeCaseStep"
        />
      </template>


      <!-- 添加UI的弹窗 -->
      <template v-if="globalConfig.testType === 'UI'" #model-content="{ selectedStep }">
        <Form :model="selectedStep" layout="vertical">
          <Form.Item label="名称">
            <Input v-model:value="selectedStep.name" />
          </Form.Item>

          <Form.Item label="操作类型">
            <Cascader
              v-model:value="currentSelectedOptions"
              :options="cascaderOptions"
              placeholder="请选择操作类型"
              :show-search="{ filter }"
              :display-render="({ labels }) => labels[labels.length - 1]"
              @change="(value) => {
                  value[value.length - 1] &&
                    (selectedStep.operationType = value[
                      value.length - 1
                    ] as string)
                }"
              />
          </Form.Item>

          <Form.Item
            v-for="(item, index) in currentSelectedValue"
            :key="index"
            :label="item.name"
          >
            <div v-if="item.field.toLowerCase().includes('locationtype')">
              <!-- @vue-expect-error -->
              <Select
                v-model:value="/* @ts-ignore */ selectedStep[item.field]"
                :options="
                  data?.ui_location_type.map((item) => ({
                    label: item.name,
                    value: item.value,
                  }))
                "
              />
            </div>
            <Input
              v-else
              v-model:value="/* @ts-ignore */ selectedStep[item.field]"
              :placeholder="`请输入${item.name}`"
            />
          </Form.Item>

          <!-- <Form.Item label="引擎类型">
            <Input v-model:value="selectedStep.engineType" disabled/>
          </Form.Item> -->

          <Form.Item label="重试类型">
            <Select v-model:value="selectedStep.retryType" :disabled="true">
              <Select.Option value="同步">同步重试</Select.Option>
              <Select.Option value="异步">异步重试</Select.Option>
            </Select>
          </Form.Item>

          <Form.Item label="重试次数">
            <InputNumber v-model:value="selectedStep.retryCount" :disabled="isRetrySwitchType"/>
          </Form.Item>
          
          <Form.Item label="首次重试间隔(单位: 秒 )">
            <InputNumber v-model:value="selectedStep.retryFirstInterval" :disabled="isRetrySwitchType"/>
          </Form.Item>

          <div flex="~ justify-around">
            <Form.Item label="是否截图">
              <Switch v-model:checked="selectedStep.isScreenshot" />
            </Form.Item>

            <Form.Item label="失败是否继续">
              <Switch v-model:checked="selectedStep.isContinue" />
            </Form.Item>
            <Form.Item label="失败是否重试(默认关闭)">
              <Switch v-model:checked="selectedStep.isRetry" />
            </Form.Item>
          </div>
        </Form>
      </template>
    </NewOrEditSteps>
  </div>

</template>
